//
// Created by alexa on 5/14/2024.
//

#include <conio.h>
#include "CrewsMenu.h"
#include "../../keydown-handler/KeydownHandler.h"
#include "../../valid-input/ValidInput.h"

void CrewsMenu::displayMenu() {
    printMenu();
    return keydownHandle(ui->getPressedKey, {
            {Keys::TAB,   [this]() {
                ui->toggleLocale();
                return displayMenu();
            }},
            {Keys::ESC,   [this]() {
                ui->setCurrentPage(Pages::MAIN_MENU);
                return;
            }},
            {Keys::KEY_1, [this]() {
                return displayCrewsList();
            }},
            {Keys::KEY_2, [this]() {
                return findAndDisplayCrewInfo();
            }},
            {Keys::KEY_3, [this]() {
                return createCrew();
            }},
            {Keys::KEY_4, [this]() {
                MaintenanceCrew *crew = findCrew();
                return deleteCrew(crew);
            }}
    });
}

CrewsMenu::CrewsMenu(i18n::Translator *t, UserInterface *ui, CrewsService *service) : Menu(t, ui), service(service) {}

MaintenanceCrew *CrewsMenu::findCrew() {
    cout << endl;
    string crewId = vi::inputString((*t)("enter-crew-id", "crews.general"));
    try {
        return service->getById(crewId);
    } catch (EntityNotFound e) {
        cout << (*t)("crew-doesnt-exist", "crews.general") << endl;
        cout << (*t)("continue", "general");
        _getch();
        ui->setCurrentPage(Pages::CREWS_MENU);
        return nullptr;
    }
}

void CrewsMenu::displayCrewInfo(MaintenanceCrew *crew) {
    if (!crew) return;
    vector<Soldier *> members = service->getSoldiersInCrew(crew->getId());
    clearScreen();
    printKeybinds();
    printCrewInfo(crew, members);
    cout << endl << (*t)("add-new-member", "crews.info") << endl;
    cout << (*t)("remove-member", "crews.info") << endl;
    cout << (*t)("delete", "crews.info") << endl;
    return keydownHandle(ui->getPressedKey, {
            {Keys::TAB,   [this, crew]() {
                ui->toggleLocale();
                return displayCrewInfo(crew);
            }},
            {Keys::ESC,   [this]() {
                ui->setCurrentPage(Pages::CREWS_MENU);
                return;
            }},
            {Keys::KEY_A, [this, crew]() {
                return addSoldierToCrew(crew);
            }},
            {Keys::KEY_M, [this, crew]() {
                return removeSoldierFromCrew(crew);
            }},
            {Keys::KEY_D, [this, crew]() {
                return deleteCrew(crew);
            }}
    });
}

void CrewsMenu::displayCrewsList() {
    vector<MaintenanceCrew *> crews = service->getAll();
    printCrewsList(crews);
    cout << endl << (*t)("get-info", "crews.list") << endl;
    return keydownHandle(ui->getPressedKey, {
            {Keys::TAB,   [this, crews]() {
                ui->toggleLocale();
                return displayCrewsList();
            }},
            {Keys::ESC,   [this]() {
                ui->setCurrentPage(Pages::CREWS_MENU);
                return;
            }},
            {Keys::KEY_I, [this]() {
                return findAndDisplayCrewInfo();
            }}
    });
}

void CrewsMenu::deleteCrew(MaintenanceCrew *crew) {
    if (!crew) return;
    service->deleteOne(crew->getId());
    cout << (*t)("successfully-deleted", "crews.delete", {{"crew-id", crew->getId()}}) << endl;
    cout << (*t)("continue", "general");
    _getch();
    ui->setCurrentPage(Pages::CREWS_MENU);
}

void CrewsMenu::printCrewsList(vector<MaintenanceCrew *> list) {
    clearScreen();
    printKeybinds();
    cout << (*t)("title", "crews.list") << endl;
    if (list.empty()) {
        cout << (*t)("empty-list", "general") << endl;
        return;
    }
    for (const auto &crew: list) {
        cout << endl;
        cout << (*t)("id", "crews.info") << ": " << crew->getId() << endl;
        cout << (*t)("members-number", "crews.info") << ": " << crew->getSoldiersIds().size() << endl;
    }
}

void CrewsMenu::printCrewInfo(MaintenanceCrew *crew, vector<Soldier *> members) {
    cout << endl;
    cout << (*t)("id", "crews.info") << ": " << crew->getId() << endl;
    cout << (*t)("crew-members", "crews.info") << ": " << endl;
    if (members.empty()) {
        cout << (*t)("no-members", "crews.info") << endl;
    } else {
        for (const auto &soldier: members) {
            cout << (*t)("id", "soldiers.info") << ": " << soldier->getId() << endl;
            cout << (*t)("fullname", "soldiers.info") << ": " << soldier->getFullname() << endl;
            cout << (*t)("rank", "soldiers.info") << ": " << soldier->getRank() << endl;
            cout << (*t)("specialization", "soldiers.info") << ": "
                 << (*t)(specToString(soldier->getSpecialization()), "soldiers.specializations") << endl;
            cout << endl;
        }
    }
}

void CrewsMenu::printMenu() {
    clearScreen();
    printKeybinds();
    cout << (*t)("title", "units.main") << endl;
    cout << "1. " << (*t)("option1", "crews.main") << endl;
    cout << "2. " << (*t)("option2", "crews.main") << endl;
    cout << "3. " << (*t)("option3", "crews.main") << endl;
    cout << "4. " << (*t)("option4", "crews.main") << endl;
    cout << (*t)("select-action", "general",
                 {
                         {"min", "1"},
                         {"max", "4"}
                 });
}

void CrewsMenu::createCrew() {
    clearScreen();
    MaintenanceCrew *crew = service->createOne();
    return displayCrewInfo(crew);
}

void CrewsMenu::addSoldierToCrew(MaintenanceCrew *crew) {
    string soldierId = vi::inputString((*t)("enter-soldier-id", "soldiers.general"));
    try {
        service->addSoldier(crew->getId(), soldierId);
        cout << (*t)("member-added", "crews.info", {{"member-id", soldierId}}) << endl;
        cout << (*t)("continue", "general");
        _getch();
        return displayCrewInfo(crew);
    } catch (EntityNotFound &e) {
        cout << (*t)("soldier-doesnt-exist", "soldiers.general") << endl;
        cout << (*t)("continue", "general");
        _getch();
        return displayCrewInfo(crew);
    }
}

void CrewsMenu::removeSoldierFromCrew(MaintenanceCrew *crew) {
    string soldierId = vi::inputString((*t)("enter-soldier-id", "soldiers.general"));
    try {
        service->removeSoldier(crew->getId(), soldierId);
        cout << (*t)("member-removed", "crews.info", {{"member-id", soldierId}}) << endl;
        cout << (*t)("continue", "general");
        _getch();
        return displayCrewInfo(crew);
    } catch (EntityNotFound e) {
        cout << (*t)("soldier-doesnt-exist", "soldiers.general") << endl;
        cout << (*t)("continue", "general");
        _getch();
        return displayCrewInfo(crew);
    }
}

void CrewsMenu::findAndDisplayCrewInfo() {
    MaintenanceCrew* crew = findCrew();
    return displayCrewInfo(crew);
}
